<?php


namespace wchat\qq\pay;


use Exception;
use wchat\common\Help;
use wchat\common\Result;
use wchat\qq\SmallProgram;

/**
 * Class Cash_Bonus
 * @package wchat\qq
 */
class Cash_Bonus extends SmallProgram
{

    public string $_cash = '/cgi-bin/hongbao/qpay_hb_mch_send.cgi';

    private array $_errors = [
        '66228701' => '红包个数超出限制',
        '66228705' => '总金额超出限制',
        '66228706' => '总金额不足以按最小金额领取每个红包',
        '66228707' => '商户签名校验失败',
        '66228708' => '重入？？',
        '66228709' => 'openid转换uin失败',
        '66228711' => '商户订单中的商户号有误',
        '66228712' => '商户订单中的日期超过范围',
        '66228713' => '余额不足',
        '66228715' => '用户未关注公众号，发送AIO消息失败',
        '66229716' => '用户禁用公众号，发AIO消息失败'
    ];

    private array $_requestParams = [];

    /**
     * @param string $value
     */
    public function setMchName(string $value): void
    {
        $this->_requestParams['mch_name'] = $value;
    }

    /**
     * @param string $value
     */
    public function setActName(string $value): void
    {
        $this->_requestParams['act_name'] = $value;
    }

    /**
     * @param string $value
     */
    public function setWishing(string $value): void
    {
        $this->_requestParams['wishing'] = $value;
    }

    /**
     * @param int $value
     */
    public function setIconId(int $value): void
    {
        $this->_requestParams['icon_id'] = $value;
    }

    /**
     * @param int $value
     */
    public function setBannerId(int $value): void
    {
        $this->_requestParams['banner_id'] = $value;
    }


    /**
     * @param string $mch_billno
     * @param string $openId
     * @param float $price
     * @return mixed
     */
    public function mch_send(string $mch_billno, string $openId, float $price): Result
    {
        $client = $this->createClient($this->_cash, $this->orderConfig($mch_billno, $openId, $price));
        if (!in_array($client->getStatusCode(), [101, 200, 201])) {
            return new Result(code: 505, message: $client->getBody());
        }
        $json = json_decode($client->getBody(), true);

        if (isset($json['return_code']) && $json['return_code'] != 'SUCCESS') {
            return new Result(code: 500, message: $json['return_msg'] ?? $json['retmsg']);
        } else if ($json['retcode'] != 0) {
            if (empty($json['retmsg']) && isset($this->_errors[$json['retcode']])) {
                $json['retmsg'] = $this->_errors[$json['retcode']];
            }
            return new Result(code: $json['retcode'], message: $json['retmsg']);
        } else {
            return new Result(code: 0, data: $json);
        }
    }

    /**
     * @param string $mch_billno
     * @param string $openId
     * @param float $price
     * @return array
     */
    private function orderConfig(string $mch_billno, string $openId, float $price): array
    {
        $requestParam['charset']      = 1;
        $requestParam['nonce_str']    = Help::random(32);
        $requestParam['mch_billno']   = $mch_billno;
        $requestParam['mch_id']       = $this->payConfig->pay->qq->mchId;
        $requestParam['qqappid']      = $this->payConfig->appId;
        $requestParam['re_openid']    = $openId;
        $requestParam['total_amount'] = $price * 100;
        $requestParam['min_value']    = $price * 100;
        $requestParam['max_value']    = $price * 100;
        $requestParam['total_num']    = 1;
        $requestParam['notify_url']   = $this->payConfig->getNotifyUrl();
        if (!empty($this->_requestParams)) {
            $requestParam = array_merge($requestParam, $this->_requestParams);
        }
        $requestParam['sign'] = Help::sign($requestParam, $this->payConfig->pay->qq->mchSecret, 'MD5');
        return $requestParam;
    }


    /**
     * @return string
     * @throws Exception
     */
    public function mchOrderNo(): string
    {
        return implode([
            $this->payConfig->pay->qq->mchId,
            date('Ymd'),
            random_int(11, 99),
            date('His'),
            random_int(11, 99)
        ]);
    }


    /**
     * @param array $requestParams
     * @return bool
     */
    public function validator(array $requestParams): bool
    {
        $notifySign = $requestParams['sign'];
        unset($requestParams['sign']);
        $sign = Help::sign($requestParams, $this->payConfig->pay->qq->mchSecret, 'MD5');

        if ($sign !== $notifySign) {
            return false;
        }

        return true;
    }


}
